package com.dingreading.cloud.mall.controller;

import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.*;
import com.dingreading.cloud.common.util.qyweixin.AccessTokenDto;
import com.dingreading.cloud.common.util.qyweixin.QyWeiXinUtil;
import com.dingreading.cloud.common.util.qyweixin.QyWeixinMsg;
import com.dingreading.cloud.mall.dto.*;
import com.dingreading.cloud.mall.entity.*;
import com.dingreading.cloud.mall.service.*;
import com.dingreading.cloud.mall.util.OrderFormV3Util;
import com.dingreading.cloud.mall.util.ShopCartUtilV2;
import com.dingreading.cloud.mall.util.redis.RedisService;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import com.mybatisflex.core.paginate.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@RefreshScope
@RestController
@RequestMapping(value = "/cancel/front/shopCart")
@Api(tags = "商城-购物车管理(作废)")
public class FrontShopCartController {

    @Value("${serverUrl}")
    private String serverUrl;

    @Value("${qyweixin.corpid}")
    private String corpid;
    @Value("${qyweixin.secret}")
    private String secret;
    @Value("${qyweixin.agentid}")
    private String agentid;
    @Value("${qyweixin.mallchatid}")
    private String mallchatid;
    @Value("${qyweixin.managerUserid}")
    private String managerUserid;
    @Value("${qyweixin.thirdUserid}")
    private String thirdUserid;
    @Value("${qyweixin.subManagerUserid}")
    private String subManagerUserid;

    @Resource
    protected ShopCartService shopCartService;
    @Resource
    protected OrderFormService orderFormService;
    @Resource
    protected StoresService storesService;
    @Resource
    protected GoodsService goodsService;
    @Resource
    protected GoodsTypeService goodsTypeService;
    @Resource
    protected GoodsTypeComboService goodsTypeComboService;
    @Resource
    protected DeliveryAddressService deliveryAddressService;
    @Resource
    protected CouponStaffService couponStaffService;
    @Resource
    protected CorporationsService corporationsService;
    @Resource
    protected WhStockInService stockInService;
    @Resource
    protected StoreGoodsDiscountService storeGoodsDiscountService;
    @Resource
    protected GoodsCategoryLogService goodsCategoryLogService;
    @Resource
    private RedisService redisService;


    @ApiOperation(value = "分页列表")
    @PostMapping(value = "/pageList", produces = "application/json; charset=UTF-8")
    public R<Object> pageList(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "分页公共类") PageUtil pageUtil,
            @RequestParam(value = "name", required = false) @ApiParam(value = "商品名") String name
    ) {
        Page<ShopCart> pageList = shopCartService.staffPageListV3(pageUtil, storeUid, staffUid, name);

        PageBeanDto data = new PageBeanDto();
        data.setTotal(pageList.getTotalRow());
        data.setList(pageList.getRecords());
        return R.ok(data);
    }


    @ApiOperation(value = "我的购物车列表")
    @PostMapping(value = "/myShopCarts", produces = "application/json; charset=UTF-8")
    public R<Object> myShopCarts(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @RequestParam(value = "name", required = false) @ApiParam(value = "商品名") String name
    ) {
        List<ShopCart> list = shopCartService.myShopCarts(storeUid, staffUid);
        double price = 0;
        double originalPrice = 0;
        double discountPrice = 0;
        if (CollectionUtils.isNotEmpty(list)) {
            for (ShopCart cart : list) {
                price = DoubleUtil.sum(price, cart.getPrice());
                originalPrice = DoubleUtil.sum(originalPrice, cart.getOriginalPrice());
                if (cart.getDiscountPrice() != null) {
                    discountPrice = DoubleUtil.sum(discountPrice, cart.getDiscountPrice());
                }
            }
        }

        MyShopCartPriceDto data = new MyShopCartPriceDto();
        data.setPrice(price);
        data.setOriginalPrice(originalPrice);
        data.setDiscountPrice(discountPrice);
        data.setList(list);
        return R.ok(data);
    }


    @ApiOperation(value = "修改数量")
    @PostMapping(value = "/editNum", produces = "application/json; charset=UTF-8")
    public R<Object> editNum(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "id") @RequestParam(value = "id") Long id,
            @ApiParam(value = "数量") @RequestParam(value = "num", required = false) Integer num,
            @ApiParam(value = "类型 1.加 0.减") @RequestParam(value = "type", required = false) Integer type
    ) {
        Stores stores = storesService.getByUid(storeUid);
        if (null == stores)
            return R.fail("门店信息获取失败");

        ShopCart data = shopCartService.getById(id);
        if (data == null)
            return R.fail("购物车记录获取失败");
        if (data.getCode() != null || !data.getStatus().equals(EnumType.ShopCart.WAIT_CONFIRM.getType()))
            return R.fail("修改失败商品状态：" + EnumType.ShopCart.getStatus(data.getStatus()));

        Goods goods = goodsService.getById(data.getGoodsId());
        if (goods == null) return R.fail("未查询到商品");
        if (!goods.getEnabled().equals(1)) return R.fail("商品已下架");
        GoodsType goodsType = goodsTypeService.getByGoodsIdAndGoodsTypeId(data.getGoodsId(), data.getGoodsTypeId());
        if (goodsType == null) return R.fail("未查询到商品规格");
        if (!goodsType.getEnabled().equals(1)) return R.fail("商品规格已下架");

        int buyNum = 0;
        if (num != null) {
            // 修改成填入的数量
            buyNum = num;
        } else if (type != null) {
            // 没有填入数量，自加1或自减1
            if (type.equals(1)) {
                buyNum = data.getBuyNum() + 1;
            } else {
                buyNum = data.getBuyNum() - 1;
            }
        } else {
            return R.fail("修改购买数量错误");
        }
        if (buyNum <= 0)
            return R.fail("购买数量必须大于0");

        if (data.getMainComboType().equals(0)) {
            // 普通商品
            // 获取库存数量
            Map<Long, Integer> stockNumMap = stockInService.getStockNumMap(Collections.singletonList(data.getGoodsTypeId()));
            Integer stockNum = stockNumMap.get(data.getGoodsTypeId());
            // 根据购买记录和出库记录获取商品规格的待出库数量
            int waitSendNum = shopCartService.getWaitSendNum(data.getGoodsTypeId());
            // 判断商品和商品规格状态、最低购买数、库存数量
            String msg = OrderFormV3Util.judgeGoodsAndGoodsType(
                    AccountUtil.isSelfStore(stores.getOperationType()), data.getMainComboType(), goods, goodsType,
                    buyNum, stockNum, waitSendNum
            );
            if (StringUtils.isNotBlank(msg))
                return R.fail(msg);

            // 轻量门店的商品折扣规则
            Double storeGoodsDiscountRate = storeGoodsDiscountService.getDiscountRate(storeUid);

            double weight = NepUtil.nullToZero(goodsType.getWeight());
            double totalWeight = DoubleUtil.mul(weight, buyNum);
            double unitPrice = goodsType.getPrice();
            double price = 0;
            double originalUnitPrice = 0;
            double originalPrice = 0;
            Double discountRate = null;
            double discountPrice = 0;

            // 计算购物车商品的价格（学科折扣）
            ShopCartPriceDto priceDto = ShopCartUtilV2.getDiscountRateUnitPrice(
                    unitPrice, goodsType.getDiscountStatus(), storeGoodsDiscountRate
            );
            originalUnitPrice = priceDto.getOriginalUnitPrice();
            originalPrice = DoubleUtil.mul(buyNum, originalUnitPrice);
            unitPrice = priceDto.getUnitPrice();
            price = DoubleUtil.mul(buyNum, unitPrice);
            discountRate = priceDto.getDiscountRate();
            discountPrice = DoubleUtil.sub(originalPrice, price);

            // 更新购物车的信息
            boolean l = shopCartService.updateShopCartInfo(
                    staffUid, id, unitPrice, price, weight, totalWeight, buyNum, originalUnitPrice, originalPrice, discountRate, discountPrice
            );
            if (!l)
                return R.fail("修改失败");
        } else {
            // 组合商品
            List<GoodsTypeCombo> goodsTypeComboList = goodsTypeComboService.listByMainGoodsIdAndMainGoodsTypeId(data.getGoodsId(), data.getGoodsTypeId());
            if (CollectionUtils.isEmpty(goodsTypeComboList))
                return R.fail("组合商品信息获取失败");

            HashBasedTable<Long, Long, GoodsTypeCombo> table = HashBasedTable.create();
            for (GoodsTypeCombo typeCombo : goodsTypeComboList) {
                table.put(typeCombo.getGoodsTypeId(), typeCombo.getGoodsId(), typeCombo);
            }

            List<ShopCart> childShopCartList = shopCartService.childListByStoreUidAndStaffUidAndUid(storeUid, staffUid, data.getUid());
            if (CollectionUtils.isEmpty(childShopCartList))
                return R.fail("组合商品内的商品信息获取失败");

            if (table.size() != childShopCartList.size())
                return R.fail("组合商品内的商品数量和购物车记录数量不一致");

            // 获取商品和商品规格信息
            List<Long> childGoodsIds = new ArrayList<>(table.columnKeySet());
            List<Long> childGoodsTypeIds = new ArrayList<>(table.rowKeySet());

            List<Goods> childGoodsList = goodsService.listByIds(childGoodsIds);
            if (CollectionUtils.isEmpty(childGoodsList) || childGoodsIds.size() != childGoodsList.size())
                return R.fail("组合商品内的商品获取失败");
            List<GoodsType> childGoodsTypeList = goodsTypeService.listByIds(childGoodsTypeIds);
            if (CollectionUtils.isEmpty(childGoodsTypeList) || childGoodsTypeIds.size() != childGoodsTypeList.size())
                return R.fail("组合商品内的商品规格获取失败");

            Map<Long, Goods> childGoodsMap = childGoodsList.stream().collect(Collectors.toMap(Goods::getId, Function.identity()));
            Map<Long, GoodsType> childGoodsTypeMap = childGoodsTypeList.stream().collect(Collectors.toMap(GoodsType::getId, Function.identity()));

            for (GoodsType childGoodsType : childGoodsTypeList) {
                if (childGoodsType.getEnabled().equals(0)) {
                    Goods childGoods = childGoodsMap.get(childGoodsType.getGoodsId());
                    return R.fail("组合商品内的商品规格已下架" + childGoods.getName() + "/" + childGoodsType.getName());
                }
            }

            // 轻量门店的商品折扣规则
            Double storeGoodsDiscountRate = storeGoodsDiscountService.getDiscountRate(storeUid);

            // 获取库存数量
            Map<Long, Integer> stockNumMap = stockInService.getStockNumMap(childGoodsTypeIds);
            // 根据购买记录和出库记录获取商品规格的待出库数量
            Map<Long, Integer> waitSendNumMap = shopCartService.getWaitSendNum(childGoodsTypeIds);

            double totalWeight = 0;
            int paymentMethod = 1;

            for (ShopCart childCart : childShopCartList) {
                Long goodsId = childCart.getGoodsId();
                Long goodsTypeId = childCart.getGoodsTypeId();
                Goods childGoods = childGoodsMap.get(goodsId);
                GoodsType childGoodsType = childGoodsTypeMap.get(goodsTypeId);

                GoodsTypeCombo goodsTypeCombo = table.get(goodsTypeId, goodsId);
                if (goodsTypeCombo == null || goodsTypeCombo.getEnabled().equals(0))
                    return R.fail("组合商品内的商品不存在或失效");
                Integer goodsTypeComboNum = goodsTypeCombo.getNum();
                if (goodsTypeComboNum == null || goodsTypeComboNum <= 0)
                    return R.fail("组合商品内的商品可购买数量错误");

                int childBuyNum = buyNum * goodsTypeComboNum;
                // 判断商品和商品规格状态
                String msg = OrderFormV3Util.judgeGoodsAndGoodsType(
                        AccountUtil.isSelfStore(stores.getOperationType()), data.getMainComboType(),
                        childGoods, childGoodsType, childBuyNum, stockNumMap.get(goodsTypeId), waitSendNumMap.get(goodsTypeId)
                );
                if (StringUtils.isNotBlank(msg))
                    return R.fail(msg);

                // 包含有银行转账
                if (paymentMethod == 1 && childGoods.getPaymentMethod().equals(2))
                    paymentMethod = 2;

                // 修改组合商品规格的购物车记录
                ShopCartUtilV2.mdyShopCart(
                        childCart, childGoods, childGoodsType, childBuyNum, staffUid, staffName, null
                );

                totalWeight = DoubleUtil.sum(totalWeight, childCart.getTotalWeight());
            }

            // 修改组合商品规格的购物车记录
            ShopCartUtilV2.mdyMainComboShopCart(
                    data, goods, goodsType, buyNum, paymentMethod, totalWeight, staffUid, staffName, storeGoodsDiscountRate
            );
            // 修改组合商品的购物车购买数量
            shopCartService.saveOrUpdate(data);
            // 修改组合商品的子购物车购买数量
            shopCartService.saveOrUpdateBatch(childShopCartList);
        }

        return R.ok();
    }


    @ApiOperation(value = "删除")
    @PostMapping(value = "/delete", produces = "application/json; charset=UTF-8")
    public R<Object> delete(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "id集合") @RequestParam(value = "ids") List<Long> ids
    ) {
        List<ShopCart> list = shopCartService.listByIds(ids);
        if (CollectionUtils.isEmpty(list))
            return R.fail("获取失败");

        // 组合商品的子购物车记录
        List<String> mainShopCartUids = list.stream()
                .filter(shopCart -> shopCart.getMainComboType().equals(1))
                .map(ShopCart::getUid)
                .distinct()
                .collect(Collectors.toList());

        long l = shopCartService.deleteByStaffUidAndIdOrMainShopCartIds(staffUid, ids, mainShopCartUids);
        if (l <= 0)
            return R.failDel();

        return R.ok();
    }


    @ApiOperation(value = "商品加入购物车")
    @PostMapping(value = "/addToShopCart", produces = "application/json; charset=UTF-8")
    public R<Object> addToShopCart(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @RequestParam(value = "goodsId") @ApiParam(value = "商品id") Long goodsId,
            @RequestParam(value = "goodsTypeId") @ApiParam(value = "商品规格id") Long goodsTypeId,
            @RequestParam(value = "num") @ApiParam(value = "数量") Integer num,
            @RequestParam(value = "remark", required = false) @ApiParam(value = "备注") String remark
    ) {
        if (num <= 0)
            return R.fail("购买数量必须大于0");

        Stores stores = storesService.getByUid(storeUid);
        if (null == stores)
            return R.fail("门店信息获取失败");
        String storesCorpUid = stores.getCorpUid();

        // 轻量门店的商品折扣规则
        Double storeGoodsDiscountRate = storeGoodsDiscountService.getDiscountRate(storeUid);

        long cartCount = shopCartService.getStaffShopCartCountV3(storeUid, storeUid, 1);
        if (cartCount >= 50) return R.fail("购物车商品已达到50件");

        Goods goods = goodsService.getById(goodsId);
        if (goods == null)
            return R.fail("商品获取失败");
        if (!goods.getEnabled().equals(1))
            return R.fail("商品已下架");
        if (goods.getFreeDeliveryId() == null || goods.getFreeDeliveryId() <= 0)
            return R.fail("商品未设置包邮模板");
        GoodsType goodsType = goodsTypeService.getByGoodsIdAndGoodsTypeId(goodsId, goodsTypeId);
        if (goodsType == null)
            return R.fail("商品规格获取失败");
        if (!goodsType.getEnabled().equals(1))
            return R.fail("商品规格已下架");

        ShopCart data = null;
        if (goodsType.getComboType().equals(0)) {
            // 普通商品
            if (!AccountUtil.isSelfStore(stores.getOperationType()) && num < goods.getMinBuyNum())
                // 非自营门店且非组合商品，判断最低购买数
                return R.fail("购买数量不能低于最少购买数");

            // 获取库存数量
            Map<Long, Integer> stockNumMap = stockInService.getStockNumMap(Collections.singletonList(goodsTypeId));
            int stockNum = stockNumMap.get(goodsTypeId);
            // 根据购买记录和出库记录获取商品规格的待出库数量
            int waitSendNum = shopCartService.getWaitSendNum(goodsTypeId);

            // 获取商品规格的真实可售数，库存数量减去待发货数量
            stockNum = OrderFormV3Util.getGoodsTypeNum(stockNum, waitSendNum);

            data = shopCartService.getByStaffIdAndGoodsIdAndTypeId(storeUid, staffUid, goodsId, goodsTypeId, 0, 0);
            if (data == null) {
                if (num > stockNum)
                    return R.fail("购买数量不能超过库存数量库存：" + stockNum);
                // 新增普通商品购物车记录
                data = ShopCartUtilV2.newShopCart(
                        goods, goodsType, storesCorpUid, storeUid, staffUid,
                        EnumType.ShopCartType.ADD.getType(), goodsType.getComboType(), KitUtil.getUuid(), num,
                        staffUid, staffName, null, storeGoodsDiscountRate
                );
            } else {
                // 更新普通商品购物车购买数量
                int buyNum = data.getBuyNum() + num;
                if (buyNum > stockNum)
                    return R.fail("购物车内商品数量已超过库存数量");
                // 修改组合商品规格的购物车记录
                ShopCartUtilV2.mdyShopCart(
                        data, goods, goodsType, buyNum, staffUid, staffName, storeGoodsDiscountRate
                );
            }
            shopCartService.saveOrUpdate(data);
        } else {
            // 组合商品
            // 获取组合商品的商品配置集合
            List<GoodsTypeCombo> goodsTypeComboList = goodsTypeComboService.listByMainGoodsIdAndMainGoodsTypeId(goodsId, goodsTypeId);
            if (CollectionUtils.isEmpty(goodsTypeComboList))
                return R.fail("组合商品内的商品规格获取失败");

            HashBasedTable<Long, Long, GoodsTypeCombo> table = HashBasedTable.create();
            for (GoodsTypeCombo goodsTypeCombo : goodsTypeComboList) {
                table.put(goodsTypeCombo.getGoodsTypeId(), goodsTypeCombo.getGoodsId(), goodsTypeCombo);
            }
            List<Long> childGoodsIds = new ArrayList<>(table.columnKeySet());
            List<Long> childGoodsTypeIds = new ArrayList<>(table.rowKeySet());

            List<Goods> childGoodsList = goodsService.listByIds(childGoodsIds);
            if (CollectionUtils.isEmpty(childGoodsList) || childGoodsIds.size() != childGoodsList.size())
                return R.fail("组合商品内的商品获取失败");
            List<GoodsType> childGoodsTypeList = goodsTypeService.listByIds(childGoodsTypeIds);
            if (CollectionUtils.isEmpty(childGoodsTypeList) || childGoodsTypeIds.size() != childGoodsTypeList.size())
                return R.fail("组合商品内的商品规格获取失败");

            Map<Long, Goods> childGoodsMap = childGoodsList.stream().collect(Collectors.toMap(Goods::getId, Function.identity()));
            Map<Long, GoodsType> childGoodsTypeMap = childGoodsTypeList.stream().collect(Collectors.toMap(GoodsType::getId, Function.identity()));

            for (Goods childGoods : childGoodsList) {
                if (childGoods.getEnabled().equals(0)) {
                    return R.fail("组合商品内的商品已下架" + childGoods.getName());
                }
            }
            for (GoodsType childGoodsType : childGoodsTypeList) {
                if (childGoodsType.getEnabled().equals(0)) {
                    Goods childGoods = childGoodsMap.get(childGoodsType.getGoodsId());
                    return R.fail("组合商品内的商品规格已下架" + childGoods.getName() + "/" + childGoodsType.getName());
                }
            }

            // 获取库存数量
            Map<Long, Integer> stockNumMap = stockInService.getStockNumMap(childGoodsTypeIds);
            // 根据购买记录和出库记录获取商品规格的待出库数量
            Map<Long, Integer> waitSendNumMap = shopCartService.getWaitSendNum(childGoodsTypeIds);

            double totalWeight = 0;
            // 商品、组合商品规格、组合子商品，只要有一个是银行转账，主购物车记录就是银行转账
            int paymentMethod = goods.getPaymentMethod();

            data = shopCartService.getByStaffIdAndGoodsIdAndTypeId(storeUid, staffUid, goodsId, goodsTypeId, 1, 1);
            if (data == null) {
                // 新增组合商品购物车记录
                String mainUid = KitUtil.getUuid();
                List<ShopCart> newList = new ArrayList<>();
                for (Table.Cell<Long, Long, GoodsTypeCombo> cell : table.cellSet()) {
                    Long cellGoodsId = cell.getColumnKey();
                    Long cellTypeIdKey = cell.getRowKey();
                    GoodsTypeCombo goodsTypeCombo = cell.getValue();
                    if (goodsTypeCombo == null)
                        return R.fail("组合商品的商品配置获取失败");

                    Goods childGoods = childGoodsMap.get(cellGoodsId);
                    GoodsType childGoodsType = childGoodsTypeMap.get(cellTypeIdKey);
                    if (childGoods == null || childGoodsType == null)
                        return R.fail("组合商品内的商品未查询到");

                    Integer waitSendNum = waitSendNumMap.get(goodsTypeCombo.getGoodsTypeId());
                    Integer stockNum = stockNumMap.get(goodsTypeCombo.getGoodsTypeId());
                    // 获取商品规格的真实可售数，库存数量减去待发货数量
                    stockNum = OrderFormV3Util.getGoodsTypeNum(stockNum, waitSendNum);

                    // 组合商品规定的子商品规格的购买数量
                    Integer goodsTypeComboNum = goodsTypeCombo.getNum();
                    // 商品规格真实购买数=购买数*组合内规定的购买数量
                    int buyNum = num * goodsTypeComboNum;
                    if (buyNum > stockNum)
                        return R.fail("组合商品内的商品库存数量不足，" + childGoods.getName() + "/" + childGoodsType.getName() + " 库存：" + stockNum);

                    // 包含有银行转账
                    if (paymentMethod == 1 && childGoods.getPaymentMethod().equals(2))
                        paymentMethod = 2;

                    ShopCart childCart = ShopCartUtilV2.newChildComboShopCart(
                            childGoods, childGoodsType, storesCorpUid, storeUid, staffUid,
                            EnumType.ShopCartType.ADD.getType(), goodsType.getComboType(), KitUtil.getUuid(), buyNum, staffUid, staffName,
                            mainUid, goods.getId(), goods.getName(), goodsType.getId(), goodsType.getName(), null
                    );

                    totalWeight = DoubleUtil.sum(totalWeight, childCart.getTotalWeight());

                    newList.add(childCart);
                }

                // 添加组合商品的购物车记录
                data = ShopCartUtilV2.newMainComboShopCart(
                        goods, goodsType, storesCorpUid, storeUid, staffUid,
                        EnumType.ShopCartType.ADD.getType(), goodsType.getComboType(), mainUid, num, staffUid, staffName,
                        paymentMethod, totalWeight, null, storeGoodsDiscountRate
                );
                newList.add(0, data);
                // 新增组合商品购物车记录
                shopCartService.saveOrUpdateBatch(newList);
            } else {
                // 更新组合商品购物车记录
                List<ShopCart> childShopCartList = shopCartService.childListByStoreUidAndStaffUidAndUid(storeUid, staffUid, data.getUid());
                if (CollectionUtils.isEmpty(childShopCartList))
                    return R.fail("组合商品内的购物车记录获取失败");

                int buyNum = data.getBuyNum() + num;
                List<ShopCart> newList = new ArrayList<>();

                for (ShopCart childCart : childShopCartList) {
                    Goods childGoods = childGoodsMap.get(childCart.getGoodsId());
                    GoodsType childGoodsType = childGoodsTypeMap.get(childCart.getGoodsTypeId());
                    if (childGoods == null || childGoodsType == null)
                        return R.fail("组合商品内的商品未查询到");
                    GoodsTypeCombo goodsTypeCombo = table.get(childCart.getGoodsTypeId(), childCart.getGoodsId());
                    if (goodsTypeCombo == null)
                        return R.fail("组合商品的商品配置获取失败");

                    Integer waitSendNum = waitSendNumMap.get(childCart.getGoodsTypeId());
                    Integer stockNum = stockNumMap.get(childCart.getGoodsTypeId());
                    // 获取商品规格的真实可售数，库存数量减去待发货数量
                    stockNum = OrderFormV3Util.getGoodsTypeNum(stockNum, waitSendNum);

                    // 组合商品规定的子商品规格的购买数量
                    Integer goodsTypeComboNum = goodsTypeCombo.getNum();
                    // 商品规格真实购买数=购买数*组合内规定的购买数量
                    int childBuyNum = buyNum * goodsTypeComboNum;
                    if (childBuyNum > stockNum)
                        return R.fail("组合商品内的商品库存数量不足，" + childGoods.getName() + "/" + childGoodsType.getName() + " 库存：" + stockNum);

                    // 包含有银行转账
                    if (paymentMethod == 1 && childGoods.getPaymentMethod().equals(2))
                        paymentMethod = 2;

                    // 修改组合商品规格的购物车记录
                    ShopCartUtilV2.mdyShopCart(
                            childCart, childGoods, childGoodsType, childBuyNum, staffUid, staffName, null
                    );

                    totalWeight = DoubleUtil.sum(totalWeight, childCart.getTotalWeight());

                    newList.add(childCart);
                }
                // 修改组合商品规格的购物车记录
                ShopCartUtilV2.mdyMainComboShopCart(
                        data, goods, goodsType, buyNum, paymentMethod, totalWeight, staffUid, staffName, storeGoodsDiscountRate
                );
                newList.add(data);
                // 更新组合商品购物车记录
                shopCartService.saveOrUpdateBatch(newList);
            }
        }

        return R.ok(data.getId());
    }


    @ApiOperation(value = "获取购物车记录详情")
    @ApiImplicitParam(name = "shopCartIds", value = "shopCartIds", allowMultiple = true, dataTypeClass = List.class, paramType = "query")
    @PostMapping(value = "/getShopCartInfo", produces = "application/json; charset=UTF-8")
    public R<Object> getShopCartInfo(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "员工代金券id") @RequestParam(value = "couponStaffId", required = false) Long couponStaffId,
            @RequestParam(value = "shopCartIds") @ApiParam(value = "购物车id集合") List<Long> shopCartIds
    ) {
        if (CollectionUtils.isEmpty(shopCartIds))
            return R.fail("请选择商品");

        Stores stores = storesService.getByUid(storeUid);
        if (null == stores)
            return R.fail("门店信息获取失败");
        if (StringUtils.isBlank(stores.getProvince()))
            return R.fail("门店未设置省市区信息");

        List<ShopCart> shopCartList = shopCartService.listRelationByIdInOrderByPrice(shopCartIds);
        if (CollectionUtils.isEmpty(shopCartList))
            return R.fail("未查询到购物车商品信息");

        boolean selfStore = AccountUtil.isSelfStore(stores.getOperationType());
        // 验证购物车商品是否有效
        R<ShopCartCheckDto> r = OrderFormV3Util.verifyShopCartToOrder(
                shopCartList, storeUid, staffUid, selfStore, false, couponStaffId
        );
        if (R.isError(r))
            return R.fail(r.getMsg());

        ShopCartCheckDto checkDto = r.getData();
        if (checkDto == null)
            return R.fail("购物车商品校验失败");

        ShopCartResultDto resultDto = new ShopCartResultDto();
        resultDto.setNum(checkDto.getNum());
        resultDto.setTotalWeight(checkDto.getTotalWeight());
        resultDto.setPrice(checkDto.getPrice());
        resultDto.setPayPrice(checkDto.getPayPrice());
        resultDto.setPaymentMethod(checkDto.getPaymentMethod());

        resultDto.setCouponName(checkDto.getCouponName());
        resultDto.setCouponStaffId(checkDto.getCouponStaffId());
        resultDto.setDeductionPrice(checkDto.getDeductionPrice());
        resultDto.setDiscountPrice(checkDto.getDiscountPrice());
        resultDto.setOriginalPrice(checkDto.getOriginalPrice());

        // 区分能否包邮
        List<ShopCart> cartList = checkDto.getShopCartList();
        List<ShopCart> childShopCartList = checkDto.getChildShopCartList();
        OrderFormV3Util.setFreeDelivery(cartList, childShopCartList, checkDto.getGoodsTypeMap(), selfStore ? 1 : 2, false, stores.getProvince());
        Map<Integer, List<ShopCart>> deliveryCartMap = cartList.stream().collect(Collectors.groupingBy(ShopCart::getFreeDeliveryStatus));
        resultDto.setFreeDeliveryList(deliveryCartMap.get(1));
        resultDto.setNotFreeDeliveryList(deliveryCartMap.get(0));

        return R.ok(resultDto);
    }

    @ApiOperation(value = "立即购买")
    @PostMapping(value = "/nowNewShopCart", produces = "application/json; charset=UTF-8")
    public R<Object> nowNewShopCart(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @RequestParam(value = "goodsId") @ApiParam(value = "商品id") Long goodsId,
            @RequestParam(value = "goodsTypeId") @ApiParam(value = "商品规格id") Long goodsTypeId,
            @RequestParam(value = "num") @ApiParam(value = "数量") Integer num,
            @RequestParam(value = "remark", required = false) @ApiParam(value = "备注") String remark
    ) {
        if (num <= 0)
            return R.fail("购买数量必须大于0");

        Stores stores = storesService.getByUid(storeUid);
        if (null == stores)
            return R.fail("门店信息获取失败");
        String storesCorpUid = stores.getCorpUid();

        Goods goods = goodsService.getById(goodsId);
        if (goods == null)
            return R.fail("商品获取失败");
        if (!goods.getEnabled().equals(1))
            return R.fail("商品已下架");
        if (goods.getFreeDeliveryId() == null || goods.getFreeDeliveryId() <= 0)
            return R.fail("商品未设置包邮模板");

        GoodsType goodsType = goodsTypeService.getByGoodsIdAndGoodsTypeId(goodsId, goodsTypeId);
        if (goodsType == null)
            return R.fail("商品规格获取失败");
        if (!goodsType.getEnabled().equals(1))
            return R.fail("商品规格已下架");

        // 轻量门店的商品折扣规则
        Double storeGoodsDiscountRate = storeGoodsDiscountService.getDiscountRate(storeUid);

        ShopCart data = null;
        if (goodsType.getComboType().equals(0)) {
            // 普通商品
            // 获取库存数量
            Map<Long, Integer> stockNumMap = stockInService.getStockNumMap(Collections.singletonList(goodsTypeId));
            int stockNum = stockNumMap.get(goodsTypeId);
            // 根据购买记录和出库记录获取商品规格的待出库数量
            int waitSendNum = shopCartService.getWaitSendNum(goodsTypeId);

            // 判断商品和商品规格状态
            String msg = OrderFormV3Util.judgeGoodsAndGoodsType(
                    AccountUtil.isSelfStore(stores.getOperationType()), goodsType.getComboType(), goods, goodsType,
                    num, stockNum, waitSendNum
            );
            if (StringUtils.isNotBlank(msg))
                return R.fail(msg);

            data = ShopCartUtilV2.newShopCart(
                    goods, goodsType, storesCorpUid, storeUid, staffUid, EnumType.ShopCartType.NOW_BUY.getType(), goodsType.getComboType(),
                    KitUtil.getUuid(), num, staffUid, staffName, null, storeGoodsDiscountRate
            );
            shopCartService.saveOrUpdate(data);
        } else {
            // 组合商品
            // 获取组合商品的商品配置集合
            List<GoodsTypeCombo> goodsTypeComboList = goodsTypeComboService.listByMainGoodsIdAndMainGoodsTypeId(goodsId, goodsTypeId);
            if (CollectionUtils.isEmpty(goodsTypeComboList))
                return R.fail("组合商品内的商品规格获取失败");

            HashBasedTable<Long, Long, GoodsTypeCombo> table = HashBasedTable.create();
            for (GoodsTypeCombo goodsTypeCombo : goodsTypeComboList) {
                table.put(goodsTypeCombo.getGoodsTypeId(), goodsTypeCombo.getGoodsId(), goodsTypeCombo);
            }
            List<Long> childGoodsIds = new ArrayList<>(table.columnKeySet());
            List<Long> childGoodsTypeIds = new ArrayList<>(table.rowKeySet());

            List<Goods> childGoodsList = goodsService.listByIds(childGoodsIds);
            if (CollectionUtils.isEmpty(childGoodsList) || childGoodsIds.size() != childGoodsList.size())
                return R.fail("组合商品内的商品获取失败");
            List<GoodsType> childGoodsTypeList = goodsTypeService.listByIds(childGoodsTypeIds);
            if (CollectionUtils.isEmpty(childGoodsTypeList) || childGoodsTypeIds.size() != childGoodsTypeList.size())
                return R.fail("组合商品内的商品规格获取失败");

            Map<Long, Goods> childGoodsMap = childGoodsList.stream().collect(Collectors.toMap(Goods::getId, Function.identity()));
            Map<Long, GoodsType> childGoodsTypeMap = childGoodsTypeList.stream().collect(Collectors.toMap(GoodsType::getId, Function.identity()));

            for (GoodsType childGoodsType : childGoodsTypeList) {
                if (childGoodsType.getEnabled().equals(0)) {
                    Goods childGoods = childGoodsMap.get(childGoodsType.getGoodsId());
                    return R.fail("组合商品内的商品规格已下架" + childGoods.getName() + "/" + childGoodsType.getName());
                }
            }

            // 获取库存数量
            Map<Long, Integer> stockNumMap = stockInService.getStockNumMap(childGoodsTypeIds);
            // 根据购买记录和出库记录获取商品规格的待出库数量
            Map<Long, Integer> waitSendNumMap = shopCartService.getWaitSendNum(childGoodsTypeIds);

            // 新增组合商品购物车记录
            List<ShopCart> newList = new ArrayList<>();
            double totalWeight = 0;
            // 商品、组合商品规格、组合子商品，只要有一个是银行转账，主购物车记录就是银行转账
            int paymentMethod = goods.getPaymentMethod();
            String mainUid = KitUtil.getUuid();
            for (Table.Cell<Long, Long, GoodsTypeCombo> cell : table.cellSet()) {
                Long cellGoodsId = cell.getColumnKey();
                Long cellTypeIdKey = cell.getRowKey();
                GoodsTypeCombo goodsTypeCombo = cell.getValue();
                if (goodsTypeCombo == null)
                    return R.fail("组合商品的商品配置获取失败");

                Goods childGoods = childGoodsMap.get(cellGoodsId);
                GoodsType childGoodsType = childGoodsTypeMap.get(cellTypeIdKey);
                if (childGoods == null || childGoodsType == null)
                    return R.fail("组合商品内的商品未查询到");

                Integer waitSendNum = waitSendNumMap.get(goodsTypeCombo.getGoodsTypeId());
                Integer stockNum = stockNumMap.get(goodsTypeCombo.getGoodsTypeId());
                // 获取商品规格的真实可售数，库存数量减去待发货数量
                stockNum = OrderFormV3Util.getGoodsTypeNum(stockNum, waitSendNum);

                // 组合商品规定的子商品规格的购买数量
                Integer goodsTypeComboNum = goodsTypeCombo.getNum();
                // 商品规格真实购买数=购买数*组合内规定的购买数量
                int buyNum = num * goodsTypeComboNum;
                if (buyNum > stockNum)
                    return R.fail("组合商品内的商品库存数量不足，" + childGoods.getName() + "/" + childGoodsType.getName() + " 库存：" + stockNum);

                // 包含有银行转账
                if (paymentMethod == 1 && childGoods.getPaymentMethod().equals(2))
                    paymentMethod = 2;

                ShopCart childCart = ShopCartUtilV2.newChildComboShopCart(
                        childGoods, childGoodsType, storesCorpUid, storeUid, staffUid,
                        EnumType.ShopCartType.NOW_BUY.getType(), goodsType.getComboType(), KitUtil.getUuid(), buyNum, staffUid, staffName,
                        mainUid, goods.getId(), goods.getName(), goodsType.getId(), goodsType.getName(), null
                );

                totalWeight = DoubleUtil.sum(totalWeight, childCart.getTotalWeight());
                newList.add(childCart);
            }

            // 添加组合商品规格的购物车记录
            data = ShopCartUtilV2.newMainComboShopCart(
                    goods, goodsType, storesCorpUid, storeUid, staffUid,
                    EnumType.ShopCartType.NOW_BUY.getType(), goodsType.getComboType(), mainUid, num, staffUid, staffName,
                    paymentMethod, totalWeight, null, storeGoodsDiscountRate
            );
            newList.add(data);

            // 新增组合商品购物车记录
            shopCartService.saveOrUpdateBatch(newList);
        }

        return R.ok(data.getId());
    }


    @ApiOperation(value = "获取购物车记录详情的可用代金券和收货地址")
    @PostMapping(value = "/getCouponAndDeliveryAddress", produces = "application/json; charset=UTF-8")
    public R<Object> getCouponAndDeliveryAddress(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @RequestParam(value = "shopCartIds") @ApiParam(value = "购物车id集合") List<Long> shopCartIds
    ) {
        // 获取收货地址
        DeliveryAddress address = deliveryAddressService.getDefault(storeUid, staffUid);
        DeliveryAddressDto addressDto = null;
        if (address != null)
            addressDto = OrderFormV3Util.getAddressDto(address);

        List<ShopCart> shopCartList = shopCartService.listRelationByIdIn(shopCartIds);
        if (CollectionUtils.isEmpty(shopCartList))
            return R.fail("未查询到购物车商品信息");

        // 套装内的商品不参与商品抵扣券
        List<Long> goodsIdList = shopCartList.stream()
                .filter(cart -> cart.getMainComboType().equals(0) || (cart.getMainComboType().equals(1) && cart.getComboType().equals(1)))
                .map(ShopCart::getGoodsId)
                .collect(Collectors.toList());

        List<Goods> goodsList = goodsService.listByIds(goodsIdList);
        if (CollectionUtils.isEmpty(goodsList))
            return R.fail("未查询到商品信息");
        Map<Long, Goods> goodsMap = goodsList.stream().collect(Collectors.toMap(Goods::getId, Function.identity()));

        double useCouponPrice = 0d;
        for (ShopCart cart : shopCartList) {
            Goods goods = goodsMap.get(cart.getGoodsId());
            if (goods == null) {
                return R.fail(cart.getGoodsName() + "-" + cart.getGoodsTypeName() + "，未查询到该商品信息");
            }
            if (goods.getCouponStatus() != null && goods.getCouponStatus().equals(1)) {
                useCouponPrice = DoubleUtil.sum(useCouponPrice, cart.getPrice());
            }
        }

        // 查询商品的分类是否满足商品分类代金券
        List<Long> categoryIdList =new ArrayList<>();
        List<GoodsCategoryLog> goodsCategoryLogs = goodsCategoryLogService.listByGoodsIdIn(goodsIdList);
        if (CollectionUtils.isNotEmpty(goodsCategoryLogs)) {
            categoryIdList = goodsCategoryLogs.stream().map(GoodsCategoryLog::getCategoryId).distinct().collect(Collectors.toList());
        }

        // 员工可使用的代金券集合
        List<CouponStaffDto> couponStaffList = null;
        // 员工不可使用的代金券集合
        List<CouponStaffDto> couponStaffNoList = null;
        if (useCouponPrice > 0) {
            couponStaffList = couponStaffService.getOrderUseCouponV2(storeUid, staffUid, useCouponPrice, goodsIdList, categoryIdList);
            if (CollectionUtils.isNotEmpty(couponStaffList)) {
                // 有效但不可使用的代金券
                List<Long> couponStaffIdList = couponStaffList.stream().map(CouponStaffDto::getId).collect(Collectors.toList());
                couponStaffNoList = couponStaffService.getOrderNotUseCouponV2(storeUid, staffUid, couponStaffIdList);
            }
        }

        CouponAndAddressDto dto = new CouponAndAddressDto();
        dto.setAddress(addressDto);
        dto.setCouponStaffList(couponStaffList);
        dto.setCouponStaffNoList(couponStaffNoList);
        return R.ok(dto);
    }


    @ApiOperation(value = "购物车新建订单")
    @PostMapping(value = "/newOrder", produces = "application/json; charset=UTF-8")
    public R<Object> newOrder(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @ApiParam(value = "购物车id集合") @RequestParam(value = "shopCartIds") List<Long> shopCartIds,
            @ApiParam(value = "送货地址id") @RequestParam(value = "deliveryId") Long deliveryId,
            @ApiParam(value = "员工代金券id") @RequestParam(value = "couponStaffId", required = false) Long couponStaffId,
            @ApiParam(value = "备注") @RequestParam(value = "remark", required = false) String remark
    ) throws Exception {
        if (CollectionUtils.isEmpty(shopCartIds))
            return R.fail("请选择商品");

        Stores stores = storesService.getByUid(storeUid);
        if (null == stores)
            return R.fail("门店信息获取失败");
        if (StringUtils.isBlank(stores.getProvince()))
            return R.fail("门店未设置省市区信息");

        Corporations corporations = corporationsService.getByUid(stores.getCorpUid());
        if (corporations == null)
            return R.fail("公司获取失败");

        DeliveryAddress delivery = deliveryAddressService.getById(deliveryId);
        if (delivery == null) return R.fail("收货地址获取失败");

        List<ShopCart> shopCartList = shopCartService.listRelationByIdIn(shopCartIds);
        if (CollectionUtils.isEmpty(shopCartList))
            return R.fail("商品获取失败");

        List<String> shopCartUids = shopCartList.stream().map(ShopCart::getUid).collect(Collectors.toList());

        // 判断自营门店
        boolean selfStore = AccountUtil.isSelfStore(stores.getOperationType());

        // 创建订单时判断购物车是否有效
        R<ShopCartCheckDto> r = OrderFormV3Util.verifyShopCartToOrder(
                shopCartList, storeUid, staffUid, selfStore, true, couponStaffId
        );
        if (R.isError(r))
            return R.fail(r.getMsg());

        ShopCartCheckDto checkDto = r.getData();
        // 订单购买的总数量
        int totalBuyNum = checkDto.getNum();
        // 订单商品总重量
        double totalWeight = checkDto.getTotalWeight();
        // 订单总金额
        double totalPrice = checkDto.getPrice();
        // 订单支付金额
        double payPrice = checkDto.getPayPrice();
        // 订单原价总金额
        double originalPrice = checkDto.getOriginalPrice();
        // 代金券抵扣金额
        double deductionPrice = checkDto.getDeductionPrice();
        // 商品折扣金额
        double discountPrice = checkDto.getDiscountPrice();
        // 代金券名称
        String couponName = checkDto.getCouponName();
        // 付款方式
        int paymentMethod = checkDto.getPaymentMethod();
        // 收款公司
        int payCorp = checkDto.getPayCorp();
        checkDto.getCouponName();
        // 商品规格
        Map<Long, GoodsType> goodsTypeMap = checkDto.getGoodsTypeMap();

        // 区分能否包邮
        List<ShopCart> cartList = checkDto.getShopCartList();
        List<ShopCart> childShopCartList = checkDto.getChildShopCartList();
        OrderFormV3Util.setFreeDelivery(cartList, childShopCartList, goodsTypeMap, selfStore ? 1 : 2, true, stores.getProvince());

        // 创建商品订单
        OrderForm form = new OrderForm();
        // 商品规格数量
        form.setGoodsTypeNum(shopCartUids.size());
        // 商品购买数量
        form.setBuyNum(totalBuyNum);
        // 订单商品总重量
        form.setWeight(totalWeight);
        // 订单原总金额
//        form.setOriginalPrice(originalPrice);
        // 订单总金额
        form.setPrice(originalPrice);
        // 订单支付金额
        form.setPayPrice(payPrice);
        // 订单的付款方式
        form.setPaymentMethod(paymentMethod);
        // 收款公司
        form.setPayCorp(payCorp);
        // 代金券信息
        form.setCouponName(couponName);
        form.setCouponStaffId(couponStaffId);
        form.setCouponPrice(deductionPrice);
        form.setDiscountPrice(discountPrice);

        // 自营门店，实际支付金额设为0
        if (selfStore) {
            form.setPayPrice(0d);
            form.setPayChannelCode(EnumType.PayChannelCode.SELF.getType());
        }
        // 签单人默认是门店的运营人员
        if (StringUtils.isNotBlank(stores.getOperateStaffUid())) {
            form.setSaleStaffUid(stores.getOperateStaffUid());
            form.setSaleStaffName(stores.getOperateStaffName());
            form.setSaleStaffPhone(stores.getOperateStaffPhone());
        }

        String code = KitUtil.getGoodsCode();
        form.setCorpUid(stores.getCorpUid());
        form.setCorpName(corporations.getCorpName());
        form.setStoreUid(storeUid);
        form.setStoreName(storeName);
        form.setStaffUid(staffUid);
        form.setStaffName(staffName);
        form.setCode(code);
        form.setProjectType(EnumType.BalanceProject.BUY_GOODS.getType());
        form.setProjectName(EnumType.BalanceProject.BUY_GOODS.getName());
        form.setStatus(EnumType.OrderForm.WAIT_CONFIRM.getType());
        form.setStatusName(EnumType.OrderForm.WAIT_CONFIRM.getName());
        form.setRemark(remark);
        form.setAddStaffUid(staffUid);
        form.setAddStaffName(staffName);
        form.setLastStaffUid(staffUid);
        form.setLastStaffName(staffName);
        // 收货地址
        form.setDeliveryId(deliveryId);
        form.setName(delivery.getName());
        form.setPhone(delivery.getPhone());
        form.setAddress(delivery.getProvinces() + delivery.getAddress());
        orderFormService.saveOrUpdate(form);

        // 更新购物车的订单编号和相关金额
        shopCartService.updateFormInfo(shopCartUids, form.getCode());
        shopCartService.dbUpdatePriceInfo(checkDto.getUpdatePriceList());

        // 非自营门店，未付款的商城订单过期后自动取消
        if (!selfStore) {
            OrderFormV3Util.addMallCodeToRedisExpire(code);
        }

        // 发送企业微信消息通知
        String accessToken = (String) redisService.get(RedisParam.QYWEINXIN_ACCESS_TOKEN);
        if (StringUtils.isBlank(accessToken)) {
            AccessTokenDto dto = QyWeiXinUtil.getAccessToken(corpid, secret);
            if (dto != null) {
                accessToken = dto.getAccess_token();
                int expires_in = dto.getExpires_in();
                // redis缓存accessToken
                redisService.set(RedisParam.QYWEINXIN_ACCESS_TOKEN, accessToken, expires_in);
            }
        }
        if (AccountUtil.isJointOperation(stores.getOperationType(), staffUid)) {
            // 采购或联营店订单
            QyWeiXinUtil.sendToUser(accessToken, agentid, thirdUserid, QyWeixinMsg.jointOperationConfirmFreeOrderMsg(serverUrl, "采购或联营店订单", form.getStoreName(), form.getCode()));
        } else {
            if (selfStore) {
                // 自营门店订单
                QyWeiXinUtil.sendToUser(accessToken, agentid, managerUserid, QyWeixinMsg.confirmFreeOrderMsg(serverUrl, "自营门店订单", form.getStoreName(), form.getCode()));
                QyWeiXinUtil.sendToUser(accessToken, agentid, subManagerUserid, QyWeixinMsg.confirmFreeOrderMsg(serverUrl, "自营门店订单", form.getStoreName(), form.getCode()));
            } else {
                // 加盟店订单
                QyWeiXinUtil.sendToChat(accessToken, mallchatid, QyWeixinMsg.confirmOrderMsg(serverUrl, form.getStoreName(), form.getCode()));
            }
        }

        return R.ok(form.getCode());
    }


    @ApiOperation(value = "获取我的购物车数量")
    @PostMapping(value = "/getShopCartNum", produces = "application/json; charset=UTF-8")
    public R<Object> getShopCartNum(
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName
    ) {
        long count = shopCartService.getStaffShopCartCountV3(storeUid, staffUid, 1);

        return R.ok(count);
    }

}